import express, { Router } from 'express'
import { PrismaClient } from '@prisma/client'
import { ResponseHelper } from '../../utils/response'
import { rewardCalculationService } from '../../services/rewardCalculationService'
import { cronService } from '../../services/cronService'
import { priceService } from '../../services/priceService'
import { adminAuthMiddleware, requireAdmin } from '../../middleware/adminAuth'
import { normalizeAssetAdjustmentInput } from '../../utils/stakingAdjustment'

const router: Router = express.Router()
const prisma = new PrismaClient()

// 所有质押管理路由都需要管理员认证（包括 PARTNER）
router.use(adminAuthMiddleware)

// 质押产品管理
// 获取质押产品列表
router.get('/products', async (req, res) => {
  try {
    const { page = 1, limit = 10, search = '', status = '' } = req.query
    const offset = (Number(page) - 1) * Number(limit)

    // 构建查询条件
    const where: any = {}

    if (search) {
      where.OR = [
        { name: { contains: String(search) } },
        { symbol: { contains: String(search) } }
      ]
    }

    if (status === 'active') {
      where.isActive = true
    } else if (status === 'inactive') {
      where.isActive = false
    }

    // 获取总数和列表数据
    const [total, products] = await Promise.all([
      prisma.stakingProduct.count({ where }),
      prisma.stakingProduct.findMany({
        where,
        skip: offset,
        take: Number(limit),
        orderBy: { createdAt: 'desc' }
      })
    ])

    // 获取NEAR价格用于显示等值KRW
    const nearPrice = await priceService.getNearPrice()

    const data = products.map(product => ({
      ...product,
      dailyRewardRate: Number(product.dailyRewardRate),
      minStakeAmount: Number(product.minStakeAmount), // NEAR数量
      maxStakeAmount: product.maxStakeAmount ? Number(product.maxStakeAmount) : null, // NEAR数量
      minStakeAmountKRW: Number(product.minStakeAmount) * nearPrice, // 等值KRW
      maxStakeAmountKRW: product.maxStakeAmount ? Number(product.maxStakeAmount) * nearPrice : null // 等值KRW
    }))

    return ResponseHelper.success(res, {
      products: data,
      total,
      page: Number(page),
      limit: Number(limit),
      totalPages: Math.ceil(total / Number(limit))
    })
  } catch (error) {
    console.error('스테이킹 상품 목록 조회에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 상품 목록 조회에 실패했습니다.')
  }
})

// 创建质押产品 - 仅管理员可操作
router.post('/products', requireAdmin, async (req, res) => {
  try {
    const {
      name,
      symbol,
      iconUrl,
      contractAddress,
      dailyRewardRate,
      minStakeAmount,
      maxStakeAmount,
      stakingPeriodDays,
      description
    } = req.body

    // 检查symbol是否已存在
    const existingProduct = await prisma.stakingProduct.findUnique({
      where: { symbol }
    })

    if (existingProduct) {
      return ResponseHelper.error(res, '해당 토큰 심볼이 이미 존재합니다.')
    }

    const product = await prisma.stakingProduct.create({
      data: {
        name,
        symbol,
        iconUrl,
        contractAddress,
        dailyRewardRate: Number(dailyRewardRate),
        minStakeAmount: Number(minStakeAmount),
        maxStakeAmount: maxStakeAmount ? Number(maxStakeAmount) : null,
        stakingPeriodDays: stakingPeriodDays ? Number(stakingPeriodDays) : null,
        description
      }
    })

    const formattedProduct = {
      ...product,
      dailyRewardRate: Number(product.dailyRewardRate),
      minStakeAmount: Number(product.minStakeAmount),
      maxStakeAmount: product.maxStakeAmount ? Number(product.maxStakeAmount) : null
    }

    return ResponseHelper.success(res, formattedProduct, '스테이킹 상품이 성공적으로 생성되었습니다.')
  } catch (error) {
    console.error('스테이킹 상품 생성에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 상품 생성에 실패했습니다.')
  }
})

// 获取单个质押产品详情
router.get('/products/:id', async (req, res) => {
  try {
    const { id } = req.params

    const product = await prisma.stakingProduct.findUnique({
      where: { id: Number(id) }
    })

    if (!product) {
      return ResponseHelper.notFound(res, '스테이킹 상품이 존재하지 않습니다.')
    }

    const data = {
      ...product,
      dailyRewardRate: Number(product.dailyRewardRate),
      minStakeAmount: Number(product.minStakeAmount),
      maxStakeAmount: product.maxStakeAmount ? Number(product.maxStakeAmount) : null
    }

    return ResponseHelper.success(res, data)
  } catch (error) {
    console.error('스테이킹 상품 상세 조회에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 상품 상세 조회에 실패했습니다.')
  }
})

// 更新质押产品 - 仅管理员可操作
router.put('/products/:id', requireAdmin, async (req, res) => {
  try {
    const { id } = req.params
    const {
      name,
      symbol,
      iconUrl,
      contractAddress,
      dailyRewardRate,
      minStakeAmount,
      maxStakeAmount,
      stakingPeriodDays,
      isActive,
      description
    } = req.body

    // 检查产品是否存在
    const existingProduct = await prisma.stakingProduct.findUnique({
      where: { id: Number(id) }
    })

    if (!existingProduct) {
      return ResponseHelper.notFound(res, '스테이킹 상품이 존재하지 않습니다.')
    }

    // 检查symbol是否被其他产品使用
    if (symbol && symbol !== existingProduct.symbol) {
      const duplicateProduct = await prisma.stakingProduct.findUnique({
        where: { symbol }
      })

      if (duplicateProduct) {
        return ResponseHelper.error(res, '해당 토큰 심볼이 이미 존재합니다.')
      }
    }

    const product = await prisma.stakingProduct.update({
      where: { id: Number(id) },
      data: {
        name,
        symbol,
        iconUrl,
        contractAddress,
        dailyRewardRate: Number(dailyRewardRate),
        minStakeAmount: Number(minStakeAmount),
        maxStakeAmount: maxStakeAmount ? Number(maxStakeAmount) : null,
        stakingPeriodDays: stakingPeriodDays ? Number(stakingPeriodDays) : null,
        isActive,
        description
      }
    })

    const formattedProduct = {
      ...product,
      dailyRewardRate: Number(product.dailyRewardRate),
      minStakeAmount: Number(product.minStakeAmount),
      maxStakeAmount: product.maxStakeAmount ? Number(product.maxStakeAmount) : null
    }

    return ResponseHelper.success(res, formattedProduct, '스테이킹 상품이 성공적으로 업데이트되었습니다.')
  } catch (error) {
    console.error('스테이킹 상품 업데이트에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 상품 업데이트에 실패했습니다.')
  }
})

// 删除质押产品 - 仅管理员可操作
router.delete('/products/:id', requireAdmin, async (req, res) => {
  try {
    const { id } = req.params

    // 检查产品是否存在
    const product = await prisma.stakingProduct.findUnique({
      where: { id: Number(id) }
    })

    if (!product) {
      return ResponseHelper.notFound(res, '스테이킹 상품이 존재하지 않습니다.')
    }

    // 注意: StakingApplication表已删除,产品可以直接删除

    await prisma.stakingProduct.delete({
      where: { id: Number(id) }
    })

    return ResponseHelper.success(res, null, '스테이킹 상품이 성공적으로 삭제되었습니다.')
  } catch (error) {
    console.error('스테이킹 상품 삭제에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 상품 삭제에 실패했습니다.')
  }
})

// 质押申请管理
// 注意: 以下API已废弃，因为StakingApplication表已删除
// 新系统中充值直接进入UserStaking，不再需要申请/审批流程

// 获取质押申请列表 (质押进度列表) - 已废弃
router.get('/applications', async (req, res) => {
  return ResponseHelper.error(res, 'API가 폐기되었습니다: StakingApplication 테이블이 삭제되었습니다. /staking-list를 사용해 UserStaking을 조회하세요.')
})

// 获取质押历史记录
router.get('/history', async (req, res) => {
  try {
    const { page = 1, limit = 10, userId = '', type = '' } = req.query
    const offset = (Number(page) - 1) * Number(limit)

    // 构建查询条件
    const where: any = {}

    if (userId) {
      where.userId = Number(userId)
    }

    if (type) {
      where.type = type
    }

    // 获取总数和列表数据
    const [total, history] = await Promise.all([
      prisma.stakingHistory.count({ where }),
      prisma.stakingHistory.findMany({
        where,
        skip: offset,
        take: Number(limit),
        orderBy: { createdAt: 'desc' },
        include: {
          user: {
            select: {
              id: true,
              name: true,
              idNumber: true,
              mobileNumber: true
            }
          }
        }
      })
    ])

    return ResponseHelper.success(res, {
      history,
      total,
      page: Number(page),
      limit: Number(limit),
      totalPages: Math.ceil(total / Number(limit))
    })
  } catch (error) {
    console.error('스테이킹 내역 조회에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 내역 조회에 실패했습니다.')
  }
})

// 获取质押奖励支付历史
router.get('/rewards', async (req, res) => {
  try {
    const { page = 1, limit = 10, userId = '' } = req.query
    const offset = (Number(page) - 1) * Number(limit)

    // 构建查询条件
    const where: any = {}

    if (userId) {
      where.userId = Number(userId)
    }

    // 获取总数和列表数据
    const [total, rewards] = await Promise.all([
      prisma.stakingReward.count({ where }),
      prisma.stakingReward.findMany({
        where,
        skip: offset,
        take: Number(limit),
        orderBy: { createdAt: 'desc' },
        include: {
          user: {
            select: {
              id: true,
              name: true,
              idNumber: true,
              mobileNumber: true
            }
          }
        }
      })
    ])

    return ResponseHelper.success(res, {
      rewards,
      total,
      page: Number(page),
      limit: Number(limit),
      totalPages: Math.ceil(total / Number(limit))
    })
  } catch (error) {
    console.error('스테이킹 보상 내역 조회에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '스테이킹 보상 내역 조회에 실패했습니다.')
  }
})

// 更新质押申请상태 - 已废弃
router.put('/applications/:id/status', async (req, res) => {
  return ResponseHelper.error(res, 'API가 폐기되었습니다: StakingApplication 테이블이 삭제되었으며 새 시스템에서는 충전 금액이 바로 UserStaking으로 들어갑니다.')
})

// 手动触发收益计算
router.post('/manual-calculate-rewards', async (req, res) => {
  try {
    console.log('관리자가 수동으로 수익 계산을 실행했습니다.')
    const result = await rewardCalculationService.manualCalculateRewards()
    return ResponseHelper.success(res, { message: result }, '수익 계산이 완료되었습니다.')
  } catch (error) {
    console.error('수동 수익 계산 실행 실패:', error)
    return ResponseHelper.serverError(res, '수익 계산에 실패했습니다.')
  }
})

// 批准质押申请（自动开始计算收益）- 已废弃
router.post('/applications/:id/approve', async (req, res) => {
  return ResponseHelper.error(res, 'API가 폐기되었습니다: StakingApplication 테이블이 삭제되었으며 새 시스템에서는 충전 금액이 바로 UserStaking으로 들어갑니다.')
})

// 获取定时任务상태
router.get('/cron-status', async (req, res) => {
  try {
    const status = cronService.getTaskStatus()
    return ResponseHelper.success(res, {
      tasks: status,
      serverTime: new Date().toISOString()
    })
  } catch (error) {
    console.error('정기 작업 상태 조회에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '정기 작업 상태 조회에 실패했습니다.')
  }
})

// 重启定时任务
router.post('/restart-cron', async (req, res) => {
  try {
    cronService.restart()
    return ResponseHelper.success(res, null, '정기 작업이 다시 시작되었습니다.')
  } catch (error) {
    console.error('정기 작업 재시작에 실패했습니다.:', error)
    return ResponseHelper.serverError(res, '정기 작업 재시작에 실패했습니다.')
  }
})

// ============ 新增: 质押本金和收益率管理接口 ============

// 调整质押本金 - 改为修改UserStaking
router.post('/adjust-staked', async (req, res) => {
  try {
    const { userId, stakedAmount } = req.body

    if (userId === undefined || stakedAmount === undefined) {
      return ResponseHelper.error(res, '매개변수가 불완전합니다')
    }

    const numericUserId = Number(userId)
    const numericStakedAmount = Number(stakedAmount)

    if (!Number.isInteger(numericUserId) || numericUserId <= 0) {
      return ResponseHelper.error(res, '유효한 사용자 ID가 아닙니다')
    }

    if (!Number.isFinite(numericStakedAmount) || numericStakedAmount < 0) {
      return ResponseHelper.error(res, '본금은 0 이상의 숫자여야 합니다')
    }

    const userStaking = await prisma.userStaking.findUnique({
      where: { userId: numericUserId }
    })

    if (!userStaking) {
      return ResponseHelper.notFound(res, '사용자의 스테이킹 기록이 없습니다')
    }

    await prisma.userStaking.update({
      where: { userId: numericUserId },
      data: {
        stakedAmount: numericStakedAmount
      }
    })

    const adjustmentState = await rewardCalculationService.syncAfterManualAdjustment(numericUserId)

    let message = '스테이킹 본금이 성공적으로 조정되었습니다'
    if (adjustmentState.cappedDueToReduction) {
      message += ' (오늘 이미 분배된 금액이 더 커서 추가 분배가 중단됩니다)'
    } else if (adjustmentState.scheduleClosedToday && adjustmentState.remainingToday > 0) {
      message += ' (금일 분배가 완료되어 변경분은 익일 계산에 반영됩니다)'
    }

    return ResponseHelper.success(res, adjustmentState, message)
  } catch (error) {
    console.error('본금 조정 오류:', error)
    return ResponseHelper.serverError(res, '본금 조정에 실패했습니다')
  }
})

// 일일 수익률 조정 - 改为修改UserStaking
router.post('/adjust-daily-rate', async (req, res) => {
  try {
    const { userId, dailyRewardRate } = req.body

    if (!userId || dailyRewardRate === undefined) {
      return ResponseHelper.error(res, '매개변수가 불완전합니다')
    }

    const numericUserId = Number(userId)
    const numericDailyRewardRate = Number(dailyRewardRate)

    if (!Number.isInteger(numericUserId) || numericUserId <= 0) {
      return ResponseHelper.error(res, '유효한 사용자 ID가 아닙니다')
    }

    if (!Number.isFinite(numericDailyRewardRate) || numericDailyRewardRate < 0 || numericDailyRewardRate > 1) {
      return ResponseHelper.error(res, '일일 수익률은 0과 1 사이의 숫자여야 합니다')
    }

    const userStaking = await prisma.userStaking.findUnique({
      where: { userId: numericUserId }
    })

    if (!userStaking) {
      return ResponseHelper.notFound(res, '사용자의 스테이킹 기록이 없습니다')
    }

    await prisma.userStaking.update({
      where: { userId: numericUserId },
      data: {
        dailyRewardRate: numericDailyRewardRate
      }
    })

    const adjustmentState = await rewardCalculationService.syncAfterManualAdjustment(numericUserId)

    let message = '일일 수익률이 성공적으로 조정되었습니다'
    if (adjustmentState.cappedDueToReduction) {
      message += ' (이미 발송된 금액이 더 커서 금일 추가 분배는 없습니다)'
    } else if (adjustmentState.scheduleClosedToday && adjustmentState.remainingToday > 0) {
      message += ' (금일 분배가 완료되어 변경분은 익일 계산에 반영됩니다)'
    }

    return ResponseHelper.success(res, adjustmentState, message)
  } catch (error) {
    console.error('수익률 조정 오류:', error)
    return ResponseHelper.serverError(res, '수익률 조정에 실패했습니다')
  }
})

// 기타 자산 조정 (锁定金额/累计收益/可提现收益与自由保有同步)
router.post('/adjust-assets', async (req, res) => {
  try {
    const {
      userId,
      stakedAmountNear,
      lockedAmountNear,
      totalRewardsKrw,
      availableRewardsKrw
    } = req.body

    if (userId === undefined) {
      return ResponseHelper.error(res, '사용자ID가 누락되었습니다')
    }

    const numericUserId = Number(userId)
    if (!Number.isInteger(numericUserId) || numericUserId <= 0) {
      return ResponseHelper.error(res, '유효한 사용자 ID가 아닙니다')
    }

    if (stakedAmountNear === undefined) {
      return ResponseHelper.error(res, '스테이킹 본금이 누락되었습니다')
    }

    const normalized = normalizeAssetAdjustmentInput({
      stakedAmountNear: Number(stakedAmountNear ?? 0),
      lockedAmountNear: Number(lockedAmountNear ?? 0),
      totalRewardsKrw: Number(totalRewardsKrw ?? 0),
      availableRewardsKrw: Number(availableRewardsKrw ?? 0)
    })

    const userStaking = await prisma.userStaking.findUnique({
      where: { userId: numericUserId }
    })

    if (!userStaking) {
      return ResponseHelper.notFound(res, '사용자의 스테이킹 기록이 없습니다')
    }

    const nearPrice = await priceService.getNearPrice()
    const totalRewardsNear = nearPrice > 0
      ? Number((normalized.totalRewardsKrw / nearPrice).toFixed(4))
      : 0
    const availableRewardsNear = nearPrice > 0
      ? Number((normalized.availableRewardsKrw / nearPrice).toFixed(4))
      : 0

    await prisma.$transaction(async (tx) => {
      await tx.userStaking.update({
        where: { userId: numericUserId },
        data: {
          stakedAmount: normalized.stakedAmountNear,
          lockedAmount: normalized.lockedAmountNear,
          totalRewardsNear,
          availableRewards: availableRewardsNear
        }
      })

      // 累计/可提现收益改为覆盖写入，防止历史 total 与 balance 不一致导致无法下调
      await tx.userBalance.upsert({
        where: { userId: numericUserId },
        update: {
          balance: normalized.availableRewardsKrw,
          total: normalized.totalRewardsKrw
        },
        create: {
          userId: numericUserId,
          balance: normalized.availableRewardsKrw,
          frozen: 0,
          total: normalized.totalRewardsKrw
        }
      })
    }, { timeout: 15000 })

    const adjustmentState = await rewardCalculationService.syncAfterManualAdjustment(numericUserId)

    return ResponseHelper.success(res, {
      userId: numericUserId,
      stakedAmountNear: normalized.stakedAmountNear,
      lockedAmountNear: normalized.lockedAmountNear,
      totalRewardsKrw: normalized.totalRewardsKrw,
      availableRewardsKrw: normalized.availableRewardsKrw,
      totalRewardsNear,
      availableRewardsNear,
      nearPrice,
      adjustmentState
    }, '자산 항목이 성공적으로 조정되었습니다')
  } catch (error) {
    console.error('자산 조정 오류:', error)
    return ResponseHelper.serverError(res, '자산 조정에 실패했습니다')
  }
})

// 수동 정산 트리거 - 改为基于UserStaking
router.post('/manual-settlement', async (req, res) => {
  try {
    const { userId } = req.body

    if (!userId) {
      return ResponseHelper.error(res, '사용자ID가 누락되었습니다')
    }

    const userStaking = await prisma.userStaking.findUnique({
      where: { userId: Number(userId) }
    })

    if (!userStaking) {
      return ResponseHelper.notFound(res, '사용자의 스테이킹 기록이 없습니다')
    }

    const nearPrice = await priceService.getNearPrice()
    const stakedAmountNear = Number(userStaking.stakedAmount)
    const lockedAmountNear = Number(userStaking.lockedAmount)
    const totalStakingBase = stakedAmountNear + lockedAmountNear
    const dailyRate = Number(userStaking.dailyRewardRate)
    const rewardNear = totalStakingBase * dailyRate
    const rewardKrw = rewardNear * nearPrice

    if (rewardNear === 0) {
      return ResponseHelper.error(res, '스테이킹 본금이 0이어서 정산할 수 없습니다')
    }

    await prisma.$transaction(async (tx) => {
      // 更新累计收益
      await tx.userStaking.update({
        where: { userId: Number(userId) },
        data: {
          totalRewardsNear: Number(userStaking.totalRewardsNear) + rewardNear,
          availableRewards: {
            increment: rewardNear
          },
          lastSettlementDate: new Date(),
          updatedAt: new Date()
        }
      })

      // 转入余额 (不再转入余额,只记录结算历史)
      // 收益保留在UserStaking.totalRewardsNear中

      // 记录结算
      await tx.stakingSettlement.create({
        data: {
          userId: Number(userId),
          stakedAmount: stakedAmountNear,
          dailyRewardRate: dailyRate,
          rewardNear,
          rewardKrw,
          nearPrice,
          settlementDate: new Date()
        }
      })

      // 记录奖励
      await tx.stakingReward.create({
        data: {
          userId: Number(userId),
          amount: rewardNear,
          txHash: `manual_settlement_${Date.now()}_${userId}`
        }
      })
    })

    return ResponseHelper.success(res, {
      rewardNear,
      rewardKrw
    }, '수동 정산이 성공적으로 완료되었습니다')
  } catch (error) {
    console.error('수동 정산 오류:', error)
    return ResponseHelper.serverError(res, '수동 정산에 실패했습니다')
  }
})

// 사용자 스테이킹 상세 조회
router.get('/user-staking/:userId', async (req, res) => {
  try {
    const { userId } = req.params

    const stakingInfo = await prisma.userStaking.findUnique({
      where: { userId: Number(userId) },
      include: {
        user: {
          select: {
            id: true,
            name: true,
            idNumber: true,
            mobileNumber: true
          }
        }
      }
    })

    if (!stakingInfo) {
      return ResponseHelper.notFound(res, '사용자의 스테이킹 기록이 없습니다')
    }

    // 获取最近的结算记录
    const recentSettlements = await prisma.stakingSettlement.findMany({
      where: { userId: Number(userId) },
      orderBy: { settlementDate: 'desc' },
      take: 10
    })

    const data = {
      ...stakingInfo,
      stakedAmount: Number(stakingInfo.stakedAmount),
      totalRewardsNear: Number(stakingInfo.totalRewardsNear),
      dailyRewardRate: Number(stakingInfo.dailyRewardRate),
      recentSettlements: recentSettlements.map(s => ({
        ...s,
        stakedAmount: Number(s.stakedAmount),
        dailyRewardRate: Number(s.dailyRewardRate),
        rewardNear: Number(s.rewardNear),
        rewardKrw: Number(s.rewardKrw),
        nearPrice: Number(s.nearPrice)
      }))
    }

    return ResponseHelper.success(res, data)
  } catch (error) {
    console.error('사용자 스테이킹 상세 조회 오류:', error)
    return ResponseHelper.serverError(res, '사용자 스테이킹 상세 조회에 실패했습니다')
  }
})

// 전체 사용자 스테이킹 목록 조회 (改为查询UserStaking表)
router.get('/staking-list', async (req, res) => {
  try {
    const { page = 1, limit = 20, search = '', exportAll = 'false' } = req.query
    const offset = (Number(page) - 1) * Number(limit)

    // 获取当前登录用户信息
    const userType = (req as any).userType;
    const currentUserId = (req as any).userId;
    const adminId = (req as any).adminId;
    const adminRole = (req as any).adminRole;
    const isPartner = (req as any).isPartner;

    // 构建查询条件 - 查询UserStaking表
    const where: any = {}

    if (search) {
      where.user = {
        OR: [
          { name: { contains: String(search) } },
          { idNumber: { contains: String(search) } },
          { mobileNumber: { contains: String(search) } }
        ]
      }
    }

    // 权限过滤：USER角色只能查看自己邀请的用户的质押信息
    if (userType === 'USER' && currentUserId) {
      const referredUsers = await prisma.user.findMany({
        where: { referredBy: currentUserId },
        select: { id: true }
      });
      if (referredUsers.length === 0) {
        return ResponseHelper.success(res, {
          list: [],
          total: 0,
          page: Number(page),
          limit: Number(limit),
          totalPages: 0
        });
      }
      where.userId = { in: referredUsers.map(u => u.id) };
    } else if (userType === 'ADMIN' && adminRole === 'PARTNER' && isPartner && adminId) {
      // 权限过滤：PARTNER只能查看自己邀请的用户的质押信息
      const partnerUsers = await prisma.user.findMany({
        where: { partnerAdminId: adminId },
        select: { id: true }
      });
      if (partnerUsers.length === 0) {
        return ResponseHelper.success(res, {
          list: [],
          total: 0,
          page: Number(page),
          limit: Number(limit),
          totalPages: 0
        });
      }
      where.userId = { in: partnerUsers.map(u => u.id) };
    }

    // 判断是否导出全部
    const isExportAll = exportAll === 'true'

    const [total, stakingList] = await Promise.all([
      prisma.userStaking.count({ where }),
      prisma.userStaking.findMany({
        where,
        ...(isExportAll ? {} : {
          skip: offset,
          take: Number(limit)
        }),
        orderBy: { stakedAmount: 'desc' },  // 按质押金额排序
        include: {
          user: {
            select: {
              id: true,
              name: true,
              idNumber: true,
              mobileNumber: true,
              balance: {
                select: {
                  balance: true,
                  total: true
                }
              }
            }
          }
        }
      })
    ])

    // 获取NEAR价格用于转换
    const nearPrice = await priceService.getNearPrice()

    const data = stakingList.map(staking => {
      const stakedAmountNear = Number(staking.stakedAmount)
      const lockedAmountNear = Number(staking.lockedAmount)
      const dailyRate = Number(staking.dailyRewardRate)
      const totalStakingBase = stakedAmountNear + lockedAmountNear
      const userBalanceRecord = (staking.user as any)?.balance
      const ledgerTotalKrw = userBalanceRecord ? Number(userBalanceRecord.total) : 0
      const freeHoldingKrw = ledgerTotalKrw
      const ledgerNearAmount = nearPrice > 0 && freeHoldingKrw > 0
        ? Number((freeHoldingKrw / nearPrice).toFixed(6))
        : 0
      const storedTotalRewardsNear = Number(staking.totalRewardsNear || 0)
      const storedAvailableRewardsNear = Number(staking.availableRewards || 0)
      const ledgerTotalRewardsKrw = freeHoldingKrw
      const ledgerAvailableRewardsKrw = freeHoldingKrw
      const ledgerTotalRewardsNear = nearPrice > 0
        ? Number((ledgerTotalRewardsKrw / nearPrice).toFixed(6))
        : 0
      const ledgerAvailableRewardsNear = nearPrice > 0
        ? Number((ledgerAvailableRewardsKrw / nearPrice).toFixed(6))
        : 0
      const sanitizedUser = {
        id: staking.user.id,
        name: staking.user.name,
        idNumber: staking.user.idNumber,
        mobileNumber: staking.user.mobileNumber
      }

      return {
        id: staking.id,
        userId: staking.userId,
        user: sanitizedUser,
        stakedAmount: stakedAmountNear,  // 质押本金(NEAR)
        lockedAmount: lockedAmountNear,  // 锁定金额(推荐奖励NEAR)
        totalRewardsNear: ledgerTotalRewardsNear,  // 장부 기준 누적收益(NEAR)
        ledgerTotalRewardsKrw,
        storedTotalRewardsNear,
        dailyRewardRate: dailyRate,  // 日收益率
        expectedDailyReward: totalStakingBase * dailyRate,  // 预计每日收益(本金+锁定)
        availableRewardsNear: ledgerAvailableRewardsNear,  // 장부 기준 자유 보유(NEAR)
        ledgerAvailableRewardsKrw,
        storedAvailableRewardsNear,
        freeHoldingNear: ledgerNearAmount,
        ledgerTotalRewardsNear,
        ledgerAvailableRewardsNear,
        freeHoldingKrw,
        lastSettlementDate: staking.lastSettlementDate,  // 最后结算时间
        createdAt: staking.createdAt,  // 创建时间
        updatedAt: staking.updatedAt  // 更新时间
      }
    })

    return ResponseHelper.success(res, {
      list: data,
      total,
      page: Number(page),
      limit: Number(limit),
      totalPages: Math.ceil(total / Number(limit))
    })
  } catch (error) {
    console.error('스테이킹 목록 조회 오류:', error)
    return ResponseHelper.serverError(res, '스테이킹 목록 조회에 실패했습니다')
  }
})

// 提前结算 - 将用户的本金和收益全部结算为KRW并清空质押
router.post('/settle-all', async (req, res) => {
  try {
    const { userId } = req.body

    if (!userId) {
      return ResponseHelper.error(res, '사용자ID가 누락되었습니다')
    }

    // 1. 获取用户质押信息
    const userStaking = await prisma.userStaking.findUnique({
      where: { userId: Number(userId) },
      include: { user: true }
    })

    if (!userStaking) {
      return ResponseHelper.error(res, '사용자의 스테이킹 기록이 없습니다')
    }

    const stakedAmount = Number(userStaking.stakedAmount)
    const lockedAmount = Number(userStaking.lockedAmount)
    const totalRewardsNear = Number(userStaking.totalRewardsNear)
    const totalPrincipal = stakedAmount + lockedAmount

    if (totalPrincipal === 0 && totalRewardsNear === 0) {
      return ResponseHelper.error(res, '결산할 금액이 없습니다')
    }

    // 2. 获取NEAR当前价格
    const nearPrice = await priceService.getNearPrice()

    // 3. 计算总金额（本金 + 收益）
    const totalNear = totalPrincipal + totalRewardsNear
    const totalKrw = totalNear * nearPrice

    // 4. 使用事务处理所有操作
    await prisma.$transaction(async (tx) => {
      // 更新或创建用户余额（使用upsert防止记录不存在）
      await tx.userBalance.upsert({
        where: { userId: Number(userId) },
        update: {
          balance: { increment: totalKrw },
          total: { increment: totalKrw }
        },
        create: {
          userId: Number(userId),
          balance: totalKrw,
          frozen: 0,
          total: totalKrw
        }
      })

      // 清空用户质押记录
      await tx.userStaking.update({
        where: { userId: Number(userId) },
        data: {
          stakedAmount: 0,
          lockedAmount: 0,
          totalRewardsNear: 0,
          availableRewards: 0,
          lastSettlementDate: new Date()
        }
      })

      // 记录结算历史
      await tx.stakingSettlement.create({
        data: {
          userId: Number(userId),
          stakedAmount: totalPrincipal,
          dailyRewardRate: Number(userStaking.dailyRewardRate),
          rewardNear: totalRewardsNear,
          rewardKrw: totalRewardsNear * nearPrice,
          nearPrice,
          settlementDate: new Date()
        }
      })
    })

    return ResponseHelper.success(res, {
      userId,
      userName: userStaking.user.name,
      principalNear: totalPrincipal,
      rewardNear: totalRewardsNear,
      totalNear,
      nearPrice,
      totalKrw
    }, '제전 결산이 완료되었습니다')

  } catch (error: any) {
    console.error('제전 결산 오류:', error)
    return ResponseHelper.serverError(res, '제전 결산에 실패했습니다')
  }
})

export default router
